home *** CD-ROM | disk | FTP | other *** search
Text File | 1992-11-12 | 38.2 KB | 1,000 lines |
- .modeL small, pascal, os_dos
- INCLUDE demo.inc
-
- .DATA
- _psp PSEG ? ; Segment of PSP
- _env PSEG ? ; Segment of environment
-
- .CODE
-
- ;* WinOpen - Saves portion of screen to allocated memory, then opens a window
- ;* with specified fill attribute. See also the WinClose procedure.
- ;*
- ;* Shows: DOS Function - 48h (Allocate Memory Block)
- ;* Instructions - movsw stosw rep
- ;*
- ;* Uses: vconfig - Video configuration structure (initialized
- ;* by calling the GetVidConfig procedure)
- ;*
- ;* Params: Row1 - Row at top of window
- ;* Col1 - Column at left edge of window
- ;* Row2 - Row at bottom of window
- ;* Col2 - Column at right edge of window
- ;* Attr - Fill attribute for window
- ;*
- ;* Return: Short integer with segment address of allocated buffer, or
- ;* 0 if unable to allocate memory
-
- WinOpen PROC USES ds di si,
- Row1:WORD, Col1:WORD, Row2:WORD, Col2:WORD, Attr:WORD
-
- GetVidOffset Row1, Col1 ; Get offset in video segment
- mov si, ax ; SI = video offset for window
- mov bx, Row2
- sub bx, Row1
- inc bx ; BX = number of window rows
- mov cx, Col2
- sub cx, Col1
- inc cx ; CX = number of columns
-
- mov ax, cx ; Compute number of video
- mul bl ; cells in window
- add ax, 3 ; Plus 3 additional entries
- shr ax, 1 ; Shift right 3 times to
- shr ax, 1 ; multiply by 2 bytes/cell,
- shr ax, 1 ; divide by 16 bytes/paragraph
- inc ax ; Add a paragraph
- push bx ; Save number of rows
- mov bx, ax ; BX = number of paragraphs
- mov ah, 48h ; Request DOS Function 48h
- int 21h ; Allocate Memory Block
- pop bx
-
- .IF carry? ; If unsuccessful,
- sub ax, ax ; return null pointer
- .ELSE
- mov es, ax ; Point ES:DI to allocated
- sub di, di ; buffer
- mov ax, si
- stosw ; Copy video offset to buffer
- mov ax, bx
- stosw ; Number of rows to buffer
- mov ax, cx
- stosw ; Number of cols to buffer
- mov ax, 160 ; Number of video cells/row
- mov ds, vconfig.sgmnt ; DS = video segment
-
- .REPEAT
- push si ; Save ptr to start of line
- push cx ; and number of columns
-
- ; For CGA adapters, WinOpen avoids screen "snow" by disabling the video prior
- ; to block memory moves, then reenabling it. Although this technique can
- ; result in brief flickering, it demonstrates the fastest way to access a
- ; block in the CGA video buffer without causing display snow. See also the
- ; StrWrite procedure for another solution to the problem of CGA snow.
-
- .IF vconfig.adapter == CGA ; If not CGA adapter,
- INVOKE DisableCga ; disable video
- .ENDIF
-
- rep movsw ; Copy one row to buffer
-
- .IF vconfig.adapter == CGA ; If CGA adapter,
- INVOKE EnableCga ; reenable CGA video
- .ENDIF
- pop cx ; Recover number of columns
- pop si ; and start of line
- add si, ax ; Point to start of next line
- dec bx ; Decrement row counter
- .UNTIL zero? ; Until no rows remain
-
- ; Screen contents (including display attributes) are now copied to buffer.
- ; Next open window, overwriting the screen portion just saved.
-
- mov ax, 0600h ; Scroll service
- mov bh, BYTE PTR Attr ; Fill attribute
- mov cx, Col1 ; CX = row/col for upper left
- mov ch, BYTE PTR Row1
- mov dx, Col2 ; DX = row/col for lower right
- mov dh, BYTE PTR Row2
- int 10h ; Blank window area on screen
- mov ax, es ; Return address of allocated
- .ENDIF ; segment
- ret
-
- WinOpen ENDP
-
-
- ;* WinClose - "Closes" a window previously opened by the WinOpen procedure.
- ;* See also the WinOpen procedure.
- ;*
- ;* Shows: DOS Function - 49h (Release Memory Block)
- ;* Instructions - lodsw
- ;* Operators - : (segment override) SEG
- ;*
- ;* Uses: vconfig - Video configuration structure (initialized
- ;* by calling the GetVidConfig procedure)
- ;*
- ;* Params: Adr - Segment address of buffer that holds screen contents
- ;* saved in WinOpen procedure
- ;*
- ;* Return: None
-
- WinClose PROC USES ds di si,
- Adr:WORD
-
- mov ds, Adr ; DS:SI points to buffer
- sub si, si
- lodsw
- mov di, ax ; DI = video offset of window
- lodsw
- mov bx, ax ; BX = number of window rows
- lodsw
- mov cx, ax ; CX = number of columns
-
- mov ax, SEG vconfig.sgmnt
- mov es, ax ; Point ES to data segment
- push es:vconfig.sgmnt
- pop es ; ES = video segment
- mov ax, 160 ; Number of video cells/row
-
- .REPEAT
- push di ; Save ptr to start of line
- push cx ; and number of columns
-
- ; Disable CGA video prior to memory move to avoid screen snow. (See the
- ; WinOpen and StrWrite procedures for further discussions on CGA snow.)
-
- .IF vconfig.adapter == CGA ; If CGA adapter,
- INVOKE DisableCga ; disable video
- .ENDIF
-
- rep movsw ; Copy one row to buffer
-
- .IF vconfig.adapter == CGA ; If CGA adapter,
- INVOKE EnableCga ; reenable CGA video
- .ENDIF
- pop cx ; Recover number of columns
- pop di ; and start of line
- add di, ax ; Point to start of next line
- dec bx ; Decrement row counter
- .UNTIL zero? ; until no rows remain
-
- mov ah, 49h ; Request DOS Function 49h
- mov es, Adr
- int 21h ; Release Memory Block
- ret
-
- WinClose ENDP
-
-
- ;* SetCurSize - Sets cursor size.
- ;*
- ;* Shows: BIOS Interrupt - 10h, Function 1 (Set Cursor Type)
- ;*
- ;* Params: Scan1 - Starting scan line
- ;* Scan2 - Ending scan line
- ;*
- ;* Return: None
-
- SetCurSize PROC,
- Scan1:WORD, Scan2:WORD
-
- mov cx, Scan2 ; CL = ending scan line
- mov ch, BYTE PTR Scan1 ; CH = starting scan line
- mov ah, 1 ; Function 1
- int 10h ; Set Cursor Type
- ret
-
- SetCurSize ENDP
-
-
- ;* GetCurSize - Gets current cursor size.
- ;*
- ;* Shows: BIOS Interrupt - 10h, Function 3 (Get Cursor Position)
- ;*
- ;* Uses: vconfig - Video configuration structure (initialized
- ;* by calling the GetVidConfig procedure)
- ;*
- ;* Params: None
- ;*
- ;* Return: Short integer with high byte = top scan line,
- ;* low byte = bottom scan line
-
- GetCurSize PROC
-
- mov ah, 3 ; Function 3
- mov bh, vconfig.dpage
- int 10h ; Get Cursor Position
- mov ax, cx ; Return cursor size
- ret
-
- GetCurSize ENDP
-
-
- ;* GetShift - Gets current shift status. Checks for extended keyboard,
- ;* and, if available, returns additional shift information.
- ;*
- ;* Shows: BIOS Interrupt - 16h, Functions 2 and 12h (Get Keyboard Flags)
- ;*
- ;* Params: None
- ;*
- ;* Return: Long integer
- ;* high word = 0 for nonextended keyboard
- ;* 1 for extended keyboard
- ;* low word has following bits set when indicated keys are pressed:
- ;* 0 - Right SHIFT 8 - Left CTRL
- ;* 1 - Left SHIFT 9 - Left ALT
- ;* 2 - CTRL 10 - Right CTRL
- ;* 3 - ALT 11 - Right ALT
- ;* 4 - SCROLL LOCK active 12 - SCROLL LOCK pressed
- ;* 5 - NUM LOCK active 13 - NUM LOCK pressed
- ;* 6 - CAPS LOCK active 14 - CAPS LOCK pressed
- ;* 7 - INSERT toggled 15 - SYS REQ pressed
-
- GetShift PROC
-
- sub dx, dx ; Assume nonextended keyboard
- mov ah, 2 ; and use Function 2
- mov es, dx ; Point ES to low memory
- .IF BYTE PTR es:[496h] & 16 ; If extended keyboard installed,
- inc dx ; set high word of return code
- mov ah, 12h ; and use Function 12h
- .ENDIF
- int 16h ; Get Keyboard Flags
- ret
-
- GetShift ENDP
-
-
- ;* GetKeyClock - Waits for keystroke while updating time at specified location
- ;* on screen.
- ;*
- ;* Shows: BIOS Interrupt - 16h, Functions 0 and 10h (Read Character)
- ;* 16h, Functions 1 and 11h (Get Keyboard Status)
- ;* DOS Functions - 2Ah (Get Date)
- ;* 2Ch (Get Time)
- ;*
- ;* Uses: vconfig - Video configuration structure (initialized
- ;* by calling the GetVidConfig procedure)
- ;*
- ;* Params: Row - Screen row for clock display
- ;* Col - Screen column for clock display
- ;*
- ;* Return: Short integer with key scan code in high byte and ASCII
- ;* character code in low byte. Low byte is 0 for special
- ;* keys (such as the "F" keys), which don't generate characters.
-
- .DATA
- PUBLIC datestr
- datestr BYTE " - - : : ", 0 ; Date/time string
- .CODE
-
- GetKeyClock PROC,
- Row:WORD, Col:WORD
-
- LOCAL service:BYTE
-
- INVOKE GetShift ; Check for extended keyboard
- mov service, 11h ; Assume Function 11h
- .IF dx != 1 ; If no extended keyboard,
- mov service, 1 ; use Function 1
- .ENDIF
-
- .WHILE 1
- mov ah, service
- int 16h ; Get Keyboard Status
- .BREAK .IF !zero? ; If no key yet, update clock
-
- ; If not monochrome, color text, or black and white, skip clock update
- ; and poll keyboard again.
-
- .CONTINUE .IF (vconfig.mode != 7) \
- && (vconfig.mode != 3) \
- && (vconfig.mode != 2)
-
- ; If 80-column text, get date and time from DOS before again
- ; polling keyboard, and display at upper right corner of screen.
-
- mov ah, 2Ch ; Request time
- int 21h ; Get Time
- mov dl, dh
- push dx ; Save seconds,
- push cx ; minutes,
- mov cl, ch ; and
- push cx ; hours
- mov ah, 2Ah ; Request date
- int 21h ; Get Date
- sub cx, 1900 ; Subtract century, CL = year
- push cx ; Save year,
- push dx ; day,
- mov dl, dh ; and
- push dx ; month
-
- mov cx, 6
- sub bx, bx
-
- .REPEAT
- pop ax ; Recover all 6 numbers in AL
- aam ; Convert to unpacked BCD
- xchg al, ah ; Switch bytes for word move
- or ax, "00" ; Make ASCII numerals
- mov WORD PTR datestr[bx], ax; Copy to string
- add bx, 3 ; at every third byte
- .UNTILCXZ
-
- INVOKE StrWrite, Row, Col, ADDR datestr
- .ENDW ; Loop again for keypress
-
- mov ah, service ; 1 or 11h, depending on keybd
- dec ah ; Set AH to 0 or 10h
- int 16h ; Get key to remove it from
- ret ; keyboard buffer
-
- GetKeyClock ENDP
-
-
- ;* GetPSP - Gets address of Program Segment Prefix. For DOS 3.0 or higher.
- ;*
- ;* Shows: DOS Function - 62h (Get PSP Address)
- ;* Instruction - call
- ;*
- ;* Params: None
- ;*
- ;* Return: Short integer with PSP segment address
- ;* or 0 if DOS version below 3.0
-
- GetPSP PROC
-
- INVOKE GetVer ; Get DOS version number
- .IF ax >= 300 ; If DOS 3.0 or higher:
- mov ah, 62h ; query DOS for PSP,
- int 21h ; get PSP Address,
- mov ax, bx ; return in AX
- .ELSE ; Else 2.0:
- sub ax, ax ; For version 2, return 0
- .ENDIF
- ret
-
- GetPSP ENDP
-
-
- ;* GetMem - Gets total size of memory and determines the largest amount of
- ;* unallocated memory available. GetMem invokes DOS Function 48h (Allocate
- ;* Memory) to request an impossibly large memory block. DOS denies the re-
- ;* quest, but returns instead the size of the largest block available. This
- ;* is the amount that GetMem returns to the calling program. See the WinOpen
- ;* procedure for an example of calling Function 48h to allocate unused memory.
- ;*
- ;* Shows: BIOS Interrupt - 12h (Get Conventional Memory Size)
- ;* Instructions - push pop ret
- ;*
- ;* Params: None
- ;*
- ;* Return: Long integer, high word = total memory in kilobytes (KB)
- ;* low word = largest block of available memory (KB)
-
- GetMem PROC
-
- int 12h ; Get total memory in kilobytes
- push ax ; Save size of memory
- mov ah, 48h ; Request memory allocation
- mov bx, 0FFFFh ; Ensure request is denied for
- ; impossibly large block
- int 21h ; Get largest available block in BX
- mov ax, bx ; Copy to AX
- mov cl, 6 ; Convert paragraphs to kilobytes by
- shr ax, cl ; dividing by 64
- pop dx ; Recover total in DX
- ret ; Return long integer DX:AX
-
- GetMem ENDP
-
-
- ;* VeriPrint - Checks if LPT1 (PRN) is available.
- ;*
- ;* Shows: BIOS Interrupt - 17h (Parallel Port Printer Driver)
- ;*
- ;* Params: None
- ;*
- ;* Return: Short integer, 1 for yes or 0 for no
-
- VeriPrint PROC
-
- mov ah, 2 ; Check printer status for
- sub dx, dx ; parallel printer (port 0)
- int 17h
- xchg dx, ax ; Put 0 (for error) in AX
-
- ; If all error bits are off and both operation bits are on, return 1
-
- .IF !(dh & 00101001y) && (dh & 10010000y)
- inc ax ; Return 1
- .ENDIF
- ret
-
- VeriPrint ENDP
-
-
- ;* IntToAsc - Converts integer to ASCII string. This procedure is useful
- ;* only for assembly language and is not intended to be callable by C.
- ;*
- ;* Shows: Instructions - aam xchg
- ;*
- ;* Entry: AX = integer (9999 max)
- ;*
- ;* Return: DX:AX = 4-digit ASCII number
-
- IntToAsc PROC
-
- cwd ; Zero DX register
- mov cx, 100 ; Divide AX by 100, yields
- div cx ; AX=quotient, DX=remainder
- aam ; Make digits unpacked BCD
- or ax, "00" ; Convert to ASCII
- xchg ax, dx ; Do same thing for DX
- aam
- or ax, "00"
- ret ; Return DX:AX = ASCII number
-
- IntToAsc ENDP
-
-
- ;* VeriAnsi - Checks for ANSI driver by writing ANSI sequence to report
- ;* cursor position. If report compares with position returned from
- ;* GetCurPos procedure, then ANSI driver is operating.
- ;*
- ;* Shows: DOS Functions - 06h (Direct Console I/O)
- ;* 0Ch (Flush Input Buffer and then Input)
- ;*
- ;* Params: None
- ;*
- ;* Return: Short integer, 1 for yes or 0 for no
-
- .DATA
- PUBLIC report
- report DB ESCAPE, "[6n$" ; ANSI Report Cursor sequence
- .CODE
-
- VeriAnsi PROC
-
- ; Get cursor position from BIOS
- INVOKE GetCurPos
- mov cx, ax ; Save it in CX
- mov dx, OFFSET report ; ANSI string to get position
- mov ah, 9 ; Request DOS String Output
- int 21h ; Write ANSI escape sequence
-
- mov ah, 6 ; Skip Esc character in
- mov dl, 0FFh ; keyboard buffer
- int 21h
- jz e_exit ; If no key, ANSI not loaded
- mov ah, 6 ; Skip '[' character
- int 21h
- jz e_exit ; If no key, ANSI not loaded
- mov ah, 6 ; Get 1st digit of cursor row
- int 21h
- jz e_exit ; If no key, ANSI not loaded
- mov bh, al ; Store in BH
- mov ah, 6 ; Get 2nd digit of cursor row
- int 21h
- jz e_exit ; If no key, ANSI not loaded
- mov bl, al ; Store in BL
- mov al, ch ; Get original row # in AL
- cbw ; AX = row # from GetCurPos
- inc ax ; Add 1 to it
- call IntToAsc ; Make ASCII digits
- cmp ax, bx ; ANSI and BIOS reports match?
- jne e_exit ; No? Then ANSI not loaded
-
- mov ax, 0C06h ; Flush remaining ANSI keys
- mov dl, 0FFh ; from buffer
- int 21h
- mov ax, 1 ; Set 1 for true
- jmp exit ; and exit
- e_exit:
- sub ax, ax ; Set 0 return code if no
- exit:
- ret ; ANSI driver installed
-
- VeriAnsi ENDP
-
-
- ;* VeriCop - Checks for coprocessor.
- ;*
- ;* Shows: BIOS Interrupt - 11h (Get Equipment Configuration)
- ;*
- ;* Params: None
- ;*
- ;* Return: Short integer, 1 for yes or 0 for no
-
- VeriCop PROC
-
- int 11h ; Check peripherals
- test al, 2 ; Coprocessor?
- mov ax, 0 ; Assume no, don't alter flags
- .IF !zero?
- inc ax ; Set to 1
- .ENDIF
- ret
-
- VeriCop ENDP
-
-
- ;* SetLineMode - Sets line mode for EGA or VGA.
- ;*
- ;* Shows: BIOS Interrupt - 10h, Function 11h (Character Generator Interface)
- ;* 10h, Function 12h (Video Subsystem Configuration)
- ;*
- ;* Uses: vconfig - Video configuration structure (initialized
- ;* by calling the GetVidConfig procedure)
- ;*
- ;* Params: Line - Requested line mode (25, 43, or 50)
- ;*
- ;* Return: Short integer with error code
- ;* 0 if successful
- ;* 1 if error
-
- SetLineMode PROC,
- Line:WORD
-
- .IF vconfig.adapter >= EGA ; If EGA or VGA:
- mov ax, Line ; Check for valid parameter
- cmp al, 25
- je line25
- cmp al, 43
- je line43
- cmp al, 50
- je line50
- jmp e_exit ; If not 25, 43, or 50, exit w/ error
- line25:
- mov al, 11h ; Set for EGA 25-line mode
- cmp vconfig.adapter, EGA ; EGA?
- je linemode ; Yes? Continue
- mov ax, 1202h ; No? Function 12h for VGA
- mov bl, 30h ; AL = 2 for 400 scan lines
- int 10h ; Reset to 400 scan lines
- mov ax, 0003 ; Reset mode (Function 0)
- int 10h ; to mode 3 (80-col text)
- mov al, 14h ; Request 8x16 char matrix
- jmp linemode
- line43:
- mov al, 12h ; Set for EGA 43-line mode
- cmp vconfig.adapter, EGA ; EGA?
- je linemode ; Yes? Continue
- mov ax, 1201h ; No? Function 12h for VGA
- mov bl, 30h ; AL = 1 for 350 scan lines
- int 10h ; Reset to 350 scan lines
- mov ax, 0003 ; Reset mode (Function 0)
- int 10h ; to mode 3 (80-col text)
- mov al, 12h ; Request 8x8 character matrix
- jmp linemode
- line50:
- cmp vconfig.adapter, VGA ; VGA?
- jne e_exit ; No? Exit with error
- mov ax, 1202h ; Yes? Function 12h
- mov bl, 30h ; AL = 2 for 400 scan lines
- int 10h ; Reset to 400 scan lines
- mov ax, 0003 ; Reset mode (Function 0)
- int 10h ; to mode 3 (80-col text)
- mov al, 12h ; Request 8x8 character matrix
- linemode:
- sub bl, bl ; Use table 0
- mov ah, 11h ; Request Function 11h
- int 10h ; Set new line mode
-
- mov ah, 12h ; Select alternate print
- mov bl, 20h ; screen for EGA and VGA
- int 10h
-
- cmp vconfig.adapter, VGA ; VGA?
- je exit ; Yes? Then exit
- cmp Line, 12h ; If EGA 43-line mode, set
- je port ; cursor through port to
- ; avoid cursor emulation bug
-
- ; Set normal cursor size, pass top and bottom scan lines
- INVOKE SetCurSize, 6, 7
- jmp exit
- port:
- mov dx, 03D4h ; Video controller address
- mov ax, 060Ah ; Set AH = 06h (cursor start)
- ; AL = 0Ah (register #)
- out dx, ax ; Update port
- mov ax, 000Bh ; Set AH = 00h (cursor end)
- ; AL = 0Bh (register #)
- out dx, ax ; Update port
- jmp exit ; Normal exit
- .ENDIF ; EGA or VGA
- e_exit:
- mov ax, 1 ; Set error code
- jmp exit2
- exit:
- sub ax, ax ; Clear error code
- exit2:
- ret
-
- SetLineMode ENDP
-
-
- ;* Pause - Waits for specified number of clocks to elapse, then returns.
- ;*
- ;* Shows: BIOS Interrupt - 1Ah, Function 0 (Real-Time Clock Driver)
- ;* Operators - LOCAL []
- ;*
- ;* Params: Duration - Desired duration in clocks, where
- ;* 18 clocks = approx 1 second
- ;*
- ;* Return: None
-
- Pause PROC,
- Duration:WORD
-
- LOCAL tick:DWORD
-
- sub ah, ah
- int 1Ah ; Get Clock Count in CX:DX
- add dx, Duration ; Add pause time to it
- adc cx, 0
- mov WORD PTR tick[0], dx ; Result is target time;
- mov WORD PTR tick[2], cx ; keep in local variable
-
- .REPEAT
- int 1Ah ; Poll clock until target time
- .UNTIL (dx >= WORD PTR tick[0]) || (cx >= WORD PTR fileinfo.time[2])
- ret
-
- Pause ENDP
-
-
- ;* Sound - Sounds speaker with specified frequency and duration.
- ;*
- ;* Shows: Instructions - in out
- ;*
- ;* Params: Freq - Desired frequency of sound in hertz
- ;* Duration - Desired duration in clocks, where
- ;* 18 clocks = approx 1 second
- ;*
- ;* Return: None
-
- Sound PROC,
- Freq:WORD, Duration:WORD
-
- mov al, 0B6h ; Initialize channel 2 of
- out 43h, al ; timer chip
- mov dx, 12h ; Divide 1,193,182 hertz
- mov ax, 34DEh ; (clock frequency) by
- div Freq ; desired frequency
- ; Result is timer clock count
- out 42h, al ; Low byte of count to timer
- mov al, ah
- out 42h, al ; High byte of count to timer
- in al, 61h ; Read value from port 61h
- or al, 3 ; Set first two bits
- out 61h, al ; Turn speaker on
-
- ; Pause, pass duration of delay
- INVOKE Pause, Duration
-
- in al, 61h ; Get port value
- xor al, 3 ; Kill bits 0-1 to turn
- out 61h, al ; speaker off
- ret
-
- Sound ENDP
-
-
- ;* WriteTTY - Displays ASCIIZ string at cursor position, in either text
- ;* or graphics mode.
- ;*
- ;* Shows: BIOS Interrupt - 10h, Function 0Eh (Write Character in TTY Mode)
- ;*
- ;* Uses: vconfig - Video configuration structure (initialized
- ;* by calling the GetVidConfig procedure)
- ;*
- ;* Params: Sptr - Pointer to ASCIIZ string
- ;* icolor - Color index (for graphics mode only)
- ;*
- ;* Return: None
-
- WriteTTY PROC USES ds si,
- Sptr:PBYTE, icolor:WORD
-
- mov bx, icolor ; BL = color index
- mov bh, vconfig.dpage ; BH = current display page
- LoadPtr ds, si, Sptr
- mov cx, -1 ; Set loop counter to maximum
- mov ah, 14 ; Function 14
-
- .REPEAT
- lodsb ; Get character from string
- .BREAK .IF al == 0 ; Exit if NULL string terminator
- int 10h ; No? Display, advance cursor
- .UNTILCXZ
-
- ret
-
- WriteTTY ENDP
-
-
- ;* Colors - Alters screen colors within a specified area by using bit
- ;* or move operations on display attribute bytes in video memory.
- ;*
- ;* Shows: Instructions - not rol ror and xor or
- ;*
- ;* Params: Logic - Code number, 0 = NOT 2 = ROR 4 = XOR 6 = MOV
- ;* 1 = ROL 3 = AND 5 = OR
- ;* Attr - Attribute mask
- ;* Row1 - Row at top of window
- ;* Col1 - Column at left edge of window
- ;* Row2 - Row at bottom of window
- ;* Col2 - Column at right edge of window
- ;*
- ;* Return: None
-
- Colors PROC USES ds si,
- Logic:WORD, Attr:WORD, Row1:WORD, Col1:WORD, Row2:WORD, Col2:WORD
-
- GetVidOffset Row1, Col1 ; Get offset in video segment
- inc ax
- mov si, ax ; SI = offset for 1st attr byte
- mov bx, Row2
- sub bx, Row1
- inc bx ; BX = number of window rows
- mov cx, Col2
- sub cx, Col1
- inc cx ; CX = number of columns
-
- mov ds, vconfig.sgmnt ; DS = video segment
- mov ax, Attr ; AL = mask for and, xor, and or
-
- .REPEAT
- push si ; Save ptr to start of line
- push cx ; and number of columns
-
- ; Disable CGA video prior to memory access to avoid screen snow. (See the
- ; WinOpen and StrWrite procedures for further discussions on CGA snow.)
-
- .IF vconfig.adapter == CGA ; If CGA adapter:
- INVOKE DisableCga ; Yes? Disable video
- .ENDIF
-
- cmp Logic, 1 ; Rotate left?
- jl c_not ; If less, do NOT
- je c_rol ; If equal, do ROL
- cmp Logic, 3 ; And?
- jl c_ror ; If less, do ROR
- je c_and ; If equal, do AND
- cmp Logic, 5 ; Or?
- jl c_xor ; If less, do XOR
- je c_or ; If equal, do OR
- c_mov:
- mov BYTE PTR [si], al ; MOV attr parameter
- add si, 2 ; into attribute byte
- loop c_mov
- jmp c_done
- c_or:
- or BYTE PTR [si], al ; OR with attr parameter
- add si, 2
- loop c_or
- jmp c_done
- c_xor:
- xor BYTE PTR [si], al ; XOR with attr parameter
- add si, 2
- loop c_xor
- jmp c_done
- c_and:
- and BYTE PTR [si], al ; AND with attr parameter
- add si, 2
- loop c_and
- jmp c_done
- c_ror:
- ror BYTE PTR [si], 1 ; Rotate right 1 bit
- add si, 2
- loop c_ror
- jmp c_done
- c_rol:
- rol BYTE PTR [si], 1 ; Rotate left 1 bit
- add si, 2
- loop c_rol
- jmp c_done
- c_not:
- not BYTE PTR [si] ; Flip bits
- add si, 2
- loop c_not
- c_done:
- .IF vconfig.adapter == CGA ; If CGA,
- INVOKE EnableCga ; reenable CGA video
- .ENDIF
-
- pop cx ; Recover number of columns
- pop si ; Recover offset for start of line
- add si, 160 ; Point to start of next line
- dec bx ; Decrement row counter
- .UNTIL zero? ; Loop while rows remain
- ret
-
- Colors ENDP
-
-
- ;* Exec - Executes a child process. Exec handles the usual chores associated
- ;* with spawning a process: (1) parsing the command line tail and loading the
- ;* FCBs with the first two arguments; (2) setting and restoring the vectors
- ;* for Interrupts 1Bh, 23h, and 24h; and (3) querying DOS for the child's
- ;* return code.
- ;*
- ;* Shows: DOS Functions - 29h (Parse Filename)
- ;* 25h (Set Interrupt Vector)
- ;* 35h (Get Interrupt Vector)
- ;* 4Bh (Execute Program)
- ;* 4Dh (Get Return Code)
- ;*
- ;* Params: Spec - Pointer to ASCIIZ specification for program file
- ;* (must include .COM or .EXE extension)
- ;* Block - Pointer to parameter block structure
- ;* CtrBrk - Pointer to new CTRL+BREAK (Interrupt 1Bh) handler
- ;* CtrlC - Pointer to new CTRL+C (Interrupt 23h) handler
- ;* Criterr - Pointer to new Critical Error (Interrupt 24h) handler
- ;*
- ;* Return: Short integer with child return code, or -1 for EXEC error
-
- Exec PROC USES ds si di,
- Spec:PBYTE, Block:PPARMBLK, CtrBrk:PTR FAR,
- CtrlC:PTR FAR, Criterr:PTR FAR
-
- Vector 1Bh, Old1Bh, CtrBrk ; Save, replace Int 1Bh vector
- Vector 23h, Old23h, CtrlC ; Save, replace Int 23h vector
- Vector 24h, Old24h, Criterr ; Save, replace Int 24h vector
-
- LoadPtr ds, bx, Block ; Point DS:BX to parameter block
- push ds ; Save segment address
- les di, (PARMBLK PTR [bx]).fcb1 ; Point ES:DI to first FCB
- lds si, (PARMBLK PTR [bx]).taddr ; Point DS:SI to command-line
- ; tail
- inc si ; Skip over count byte
-
- mov ax, 2901h ; Set AH to request Function 29h
- ; AL = flag to skip leading blanks
- int 21h ; Parse command-line into first FCB
- pop es ; Recover seg addr of parameter block
- les di, (PARMBLK PTR es:[bx]).fcb2 ; Point ES:DI to second FCB
- mov ax, 2901h ; Request DOS Function #29h again
- int 21h ; Parse command-line into second FCB
-
- push bp ; Save only important register
- mov WORD PTR cs:OldStk[0], sp
- mov WORD PTR cs:OldStk[2], ss
- LoadPtr es, bx, Block ; ES:BX points to param block
- LoadPtr ds, dx, Spec ; DS:DX points to path spec
- mov ax, 4B00h ; AH = DOS Function 4Bh
- ; AL = 0 for load and execute
- int 21h ; Execute Program
- mov sp, WORD PTR cs:OldStk[0] ; Reset stack pointers
- mov ss, WORD PTR cs:OldStk[2]
- pop bp ; Recover saved register
-
- ; Restore vectors for Interrupts 1Bh, 23h, and 24h.
-
- mov ax, 251Bh ; AH = DOS Function 25h
- ; AL = interrupt number
- lds dx, cs:Old1Bh ; DS:DX = original vector
- int 21h ; Set Interrupt 1Bh Vector
- mov al, 23h ; AL = interrupt number
- lds dx, cs:Old23h ; DS:DX = original vector
- int 21h ; Set Interrupt 23h Vector
- mov al, 24h ; AL = interrupt number
- lds dx, cs:Old24h ; DS:DX = original vector
- int 21h ; Set Interrupt 24h Vector
-
- mov ax, -1 ; Set error code
- .IF !carry? ; If no EXEC error:
- mov ah, 4Dh ; Request child's code
- int 21h ; Get Return Code
- sub ah, ah ; Make short integer
- .ENDIF
- ret
-
- Old1Bh FPVOID ? ; Keep vectors for Interrupts
- Old23h FPVOID ? ; 1Bh, 23h, and 24h in code
- Old24h FPVOID ? ; segment, but nonexecutable
- OldStk FPVOID ? ; Keep stack pointer
-
- Exec ENDP
-
-
- ;* BinToHex - Converts binary word to 6-byte hexadecimal number in
- ;* ASCIIZ string. String is right justified and includes "h" radix.
- ;*
- ;* Shows: Instruction - xlat
- ;*
- ;* Params: Num - Number to convert to hex string
- ;* Sptr - Pointer to 6-byte string
- ;*
- ;* Return: None
-
- .DATA
- hex BYTE "0123456789ABCDEF" ; String of hex numbers
-
- .CODE
- BinToHex PROC USES di,
- Num:WORD, Sptr:PBYTE
-
- LoadPtr es, di, Sptr ; Point ES:DI to 6-byte string
- mov bx, OFFSET hex ; Point DS:BX to hex numbers
- mov ax, Num ; Number in AX
- mov cx, 2 ; Loop twice for two bytes
-
- .REPEAT
- xchg ah, al ; Switch bytes
- push ax ; Save number
- shr al, 1 ; Shift high nibble to low
- shr al, 1
- shr al, 1
- shr al, 1
- xlat ; Get equivalent ASCII number in AL
- stosb ; Copy to 6-byte string, increment DI
- pop ax ; Recover number
- push ax ; Save it again
- and al, 00001111y ; Mask out high nibble
- xlat ; Get equivalent ASCII number in AL
- stosb ; Copy to 6-byte string, increment DI
- pop ax ; Recover number
- .UNTILCXZ ; Do next byte
- mov ax, 'h' ; Put null, 'h' radix in AX
- stosw ; Copy to last two bytes in string
- ret
-
- BinToHex ENDP
-
-
- ;* NewBlockSize - Adjusts size of allocated memory block.
- ;*
- ;* Shows: DOS Function - 4Ah (Resize Memory Block)
- ;*
- ;* Params: Adr - Segment address of block
- ;* Resize - Requested block size in paragraphs
- ;*
- ;* Return: Short integer error code
- ;* 0 if successful
- ;* 1 if error
-
- NewBlockSize PROC,
- Adr:WORD, Resize:WORD
-
- mov ax, Adr ; Get block address
- mov es, ax ; Point ES to block
- mov bx, Resize ; New block size
- mov ah, 4Ah ; Function number
- int 21h ; Resize Memory Block
- ret
-
- NewBlockSize ENDP
-
-
- ;* Initialize - Initializes global variables _psp and _env, which are defined
- ;* in the DEMO.INC include file. If used with a DOS version less than 3.0,
- ;* this procedure will not produce valid results unless it is called before
- ;* changing the ES register. This is because at program entry ES points to
- ;* the Program Segment Prefix (PSP).
- ;*
- ;* Params: None
- ;*
- ;* Return: None
-
- Initialize PROC
-
- INVOKE GetPSP ; Get segment address of PSP
- .IF ax == 0 ; If less than DOS 3.0,
- mov es, ax ; reload ES with PSP address
- .ENDIF
-
- mov _psp, es ; Initialize variable with PSP address
- mov ax, es:[2Ch] ; Get environment seg from PSP
- mov _env, ax ; Store it
- ret
-
- Initialize ENDP
-
- END
-